home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
pc
/
files
/
t_unix
/
j109lxa4.tar
/
mailbox.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-04
|
47KB
|
1,902 lines
/* NOTE: because of size, the previous 'mailbox.c' has been
* split in 3 parts:
* mboxcmd.c, containing the 'mbox' subcommands,
* mailbox.c, containing some user mailbox commands, and
* mailbox2.c, containing the remaining user commands.
* 921125 - WG7J
*/
/* There are only two functions in this mailbox code that depend on the
* underlying protocol, namely mbx_getname() and dochat(). All the other
* functions can hopefully be used without modification on other stream
* oriented protocols than AX.25 or NET/ROM.
*
* SM0RGV 890506, most work done previously by W9NK
*
*** Changed 900114 by KA9Q to use newline mapping features in stream socket
* interface code; everything here uses C eol convention (\n)
*
* Numerous new commands and other changes by SM0RGV, 900120
*
* Gateway function now support outgoing connects with the user's call
* with inverted ssid. Users can connect to system alias as well...
* See also several mods in socket.c,ax25.c and others
* 11/15/91, WG7J/PA3DIS
*
* Userlogging, RM,VM and KM commands, and R:-line interpretation
* added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
*
* Inactivity timeout-disconnect added 920325 and later - WG7J
*
* mbxrecvline() now can gobble up suboptions - 94/02/14 VE4WTS
*/
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#ifdef MSDOS
#include <alloc.h>
#endif
#include <stdlib.h>
#include <string.h>
#ifdef UNIX
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "global.h"
#include "config.h"
#include "timer.h"
#include "proc.h"
#include "socket.h"
#include "usock.h"
#include "session.h"
#include "smtp.h"
#include "dirutil.h"
#include "telnet.h"
#include "ftp.h"
#include "ftpserv.h"
#include "commands.h"
#include "netuser.h"
#include "files.h"
#include "bm.h"
#include "pktdrvr.h"
#include "ax25.h"
#include "mailbox.h"
#include "ax25mail.h"
#include "nr4mail.h"
#include "cmdparse.h"
#include "mailfor.h"
#ifdef MAILBOX
/* Log all gateway connects to the logfile - WG7J */
#define GWTRACE 1
/* By setting the fp to NULL, we can check in exitbbs()
* wether a tempfile has been closed or not - WG7J
*/
#define MYFCLOSE(x) { fclose(x); x = (FILE *) 0; }
/*
#define MBDEBUG
*/
extern time_t StartTime;
extern char Myalias[];
struct mbx *Mbox;
int BbsUsers;
int Totallogins;
extern char *Mtmsg;
extern int MAttended;
extern unsigned Maxlet;
extern char Mbpasswd[];
extern char Noperm[];
extern char Nosock[];
extern char MboxId[];
char Loginbanner[] = "\nKA9Q NOS (%s)\n\n";
char Mbwelcome[] = "\nWelcome %s,\n";
char Mbbanner[] = "to the %s TCP/IP Mailbox (%s)\n";
char CurUsers[] = "Currently %d user(s)\n";
char Howtoend[] = "End with /EX or ^Z in first column (^A aborts):\n";
char MsgAborted[] = "Msg aborted\n";
#ifdef MAILCMDS
char CcLine[] = "Cc: ";
char Mbwarning[] = "Third Party mail is not permitted.\n";
int MbSent;
int MbRead;
int MbRecvd;
#ifdef MBFWD
int MbForwarded;
#endif
#endif
char Mbmenu[] = "Current msg# %d.\n?,"
#ifdef MAILCMDS
"A,"
#endif
"B,C,D,E,F,H,I,IH,IP,J,K,"
#ifdef MAILCMDS
"L,"
#endif
"M,"
#ifdef NETROM
"N,NR,"
#endif
"O,P,"
#ifdef CALLCLI
"Q,"
#endif
#ifdef MAILCMDS
"R,S,"
#endif
"T,U,"
#ifdef MAILCMDS
"V,"
#endif
"W,X,Z >\n";
extern char Mbnrid[];
#ifdef MAILCMDS
#ifdef NETROM
#ifdef CALLCLI
char Longmenu[] = "?)help A)rea B)ye C)onnect D)wnload E)scape F)inger\n"
"H)elp I)nfo IH)eard IP)route J)heard K)ill L)ist M)boxusers\n"
"N)odes O)perator P)orts Q)uery R)ead S)end T)elnet\n"
"U)pload V)erbose W)hat X)pert Z)ap\n";
#else
char Longmenu[] = "?)help A)rea B)ye C)onnect D)wnload E)scape F)inger\n"
"H)elp I)nfo IH)eard IP)route J)heard K)ill L)ist M)boxusers\n"
"N)odes O)perator P)orts R)ead S)end T)elnet\n"
"U)pload V)erbose W)hat X)pert Z)ap\n";
#endif /*CALLCLI*/
#else /*NETROM*/
#ifdef CALLCLI
char Longmenu[] = "?)help A)rea B)ye C)onnect D)wnload E)scape F)inger H)elp\n"
"I)nfo IH)eard IP)route J)heard K)ill L)ist M)boxusers O)perator\n"
"P)orts Q)uery R)ead S)end T)elnet U)pload V)erbose\n"
"W)hat X)pert Z)ap\n";
#else
char Longmenu[] = "?)help A)rea B)ye C)onnect D)wnload E)scape F)inger H)elp\n"
"I)nfo IH)eard IP)route J)heard K)ill L)ist M)boxusers O)perator P)orts\n"
"R)ead S)end T)elnet U)pload V)erbose W)hat X)pert Z)ap\n";
#endif /*CALLCLI*/
#endif /*NETROM*/
#else /* MAILCMDS */
#ifdef NETROM
#ifdef CALLCLI
char Longmenu[] = "?)help B)ye C)onnect D)wnload E)scape F)inger H)elp I)nfo IH)eard\n"
"IP)route J)heard M)boxusers N)odes O)perator P)orts Q)uery T)elnet\n"
"U)pload W)hat X)pert Z)ap\n";
#else
char Longmenu[] = "?)help B)ye C)onnect D)wnload E)scape F)inger H)elp I)nfo IH)eard\n"
"IP)route J)heard M)boxusers N)odes O)perator P)orts T)elnet U)pload W)hat\n"
"X)pert Z)ap\n";
#endif /*CALLCLI*/
#else /*NETROM*/
#ifdef CALLCLI
char Longmenu[] = "?)help B)ye C)onnect D)wnload E)scape F)inger H)elp I)nfo IH)eard\n"
"IP)route J)heard M)boxusers O)perator P)orts Q)uery T)elnet U)pload W)hat\n"
"X)pert Z)ap\n";
#else
char Longmenu[] = "?)help B)ye C)onnect D)wnload E)scape F)inger H)elp I)nfo IH)eard\n"
"IP)route J)heard M)boxusers O)perator P)orts T)elnet U)pload W)hat X)pert Z)ap\n";
#endif /*CALLCLI*/
#endif /*NETROM*/
#endif /* MAILCMDS */
extern int dombusers __ARGS((int argc,char *argv[],void *p));
extern int dombpast __ARGS((int argc,char *argv[],void *p));
extern int doarea __ARGS((int argc,char *argv[],void *p));
extern int dombstatus __ARGS((int argc,char *argv[],void *p));
extern int dombmailstats __ARGS((int argc,char *argv[],void *p));
void mboxredundant __ARGS((struct mbx *m));
#ifdef CALLCLI
static int dombcallbook __ARGS((int argc,char *argv[],void *p));
#endif
extern int doipheard __ARGS((int argc,char *argv[],void *p));
static int mbx_getname __ARGS((struct mbx *m));
static int dochat __ARGS((int argc,char *argv[],void *p));
extern int Mbnewmail;
extern int Usenrid;
extern int MBSecure;
extern int Mbsendquery;
#ifdef MBXTDISC
extern int32 Mbtdiscinit;
#endif
int
dombports(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
struct mbx *m = (struct mbx *)p;
tputs("Available ports:\n");
for(ifp=Ifaces;ifp!=NULLIF;ifp=ifp->next)
if(ifp->type == CL_AX25 && \
(!(ifp->flags & HIDE_PORT) || (m->privs & SYSOP_CMD)) ) {
tprintf("%-7s",ifp->name);
if(ifp->descr != NULLCHAR)
tprintf(": %s",ifp->descr);
else
tputc('\n');
}
tputc('\n');
return 0;
}
/* This is called by the finger-daemon */
void
listusers(s)
int s;
{
int outsave;
struct mbx m;
m.privs = 0;
m.stype = ' ';
#ifdef notdef
usprintf(s,"\nCurrent remote users:\n");
#endif
outsave = Curproc->output;
Curproc->output = s;
dombusers(0,NULLCHARP,&m);
Curproc->output = outsave;
}
struct mbx *
newmbx()
{
struct mbx *m,*new;
if((new = (struct mbx *) callocw(1,sizeof(struct mbx))) == NULLMBX)
return NULLMBX;
BbsUsers++;
/* add it into the list */
if((m=Mbox) == NULLMBX)
Mbox = new;
else {
while(m->next)
m=m->next;
m->next = new;
}
return new;
}
static int
mbx_getname(m)
struct mbx *m;
{
char *cp;
FILE *tfp;
union sp sp;
char tmp[MAXSOCKSIZE];
int len = MAXSOCKSIZE;
int anony = 0;
int oldmode;
int founddigit=0;
int count=0;
#ifdef AX25
int32 flags;
int ax_25 = 0;
struct usock *up;
#endif
sp.p = tmp;
sp.sa->sa_family = AF_LOCAL; /* default to AF_LOCAL */
getpeername(m->user,tmp,&len);
m->family = sp.sa->sa_family;
m->path = mallocw(MBXLINE);
/* This is one of the two parts of the mbox code that depends on the
* underlying protocol. We have to figure out the name of the
* calling station. This is only practical when AX.25 or NET/ROM is
* used. Telnet users have to identify themselves by a login procedure.
*/
#ifdef __GNUC__
flags = 0; /* silence "uninitialized" warning */
#endif
switch(sp.sa->sa_family){
#ifdef AX25
case AF_AX25:
/* If this is not to the convers call, and this port is
* set for NO_AX25, then disconnect ! - WG7J
*/
if((m->type != CONF_LINK) && ((up = itop(m->user)) != NULLUSOCK) ) {
if((flags=up->cb.ax25->iface->flags) & NO_AX25)
return -1;
}
ax_25 = 1;
/* note fallthrough */
case AF_NETROM:
/* NETROM and AX25 socket address structures are "compatible" */
/* Save user call, in case user wants to use gateway function */
memcpy(m->call,sp.ax->ax25_addr,AXALEN);
m->call[ALEN] &= 0xfc;/*Make sure E-bit isn't set !*/
pax25(m->name,sp.ax->ax25_addr);
cp = strchr(m->name,'-');
if(cp != NULLCHAR) /* get rid of SSID */
*cp = '\0';
/* SMTP wants the name to be in lower case */
cp = m->name;
while(*cp){
if(isupper(*cp))
*cp = tolower(*cp);
++cp;
}
anony = 1;
/* Try to find the privileges of this user from the userfile */
if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony)) == -1){
m->privs = 0;
free(m->path);
m->path = NULLCHAR;
}
if(m->privs & EXCLUDED_CMD)
return -1;
if(ax_25)
if(((flags & USERS_ONLY) && (m->privs & IS_BBS)) ||
((flags & BBS_ONLY) && !(m->privs & IS_BBS)) ||
((flags & SYSOP_ONLY) && !(m->privs & SYSOP_CMD)))
return -1;
return 0;
#endif
case AF_LOCAL:
case AF_INET:
m->state = MBX_LOGIN;
tprintf(Loginbanner,Hostname);
if(Mtmsg != NULLCHAR)
tputs(Mtmsg);
for(;;){
/* Maximum of 3 tries - WG7J */
if(count++ == 3)
return -1;
oldmode = sockmode(m->user,SOCK_ASCII);
tputs("login: ");
usflush(m->user);
if(mbxrecvline(m) == -1)
return -1;
if(*m->line == 4) /* Control-d */
return -1;
if(*m->line == '\0')
continue;
/* add a little test to avoid 'Mailfile busy' syndrome - WG7J */
if((cp=strchr(m->line,'.')) != NULLCHAR)
*cp = '_';
if((cp=strchr(m->line,'/')) != NULLCHAR)
*cp = '_';
if((cp=strchr(m->line,'\\')) != NULLCHAR)
*cp = '_';
if((tfp=fopen(m->line,"w")) == NULL) /* Invalid name */
continue;
fclose(tfp);
unlink(m->line);
if(strlen(m->line) < sizeof(m->name))
strcpy(m->name,m->line);
else /* Too long! */
continue;
tprintf("Password: %c%c%c",IAC,WILL,TN_ECHO);
usflush(m->user);
sockmode(m->user,SOCK_BINARY);
if(mbxrecvline(m) == -1)
return -1;
tprintf("%c%c%c",IAC,WONT,TN_ECHO);
sockmode(m->user,oldmode);
tputc('\n');
usflush(m->user);
/* This is needed if the password was send before the
* telnet no-echo options were receied. We neeed to
* flush the eold sequence from the input buffers, sigh
*/
if(socklen(m->user,0))/* discard any remaining input */
recv_mbuf(m->user,NULL,0,NULLCHAR,0);
if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony))
!= -1){
if(anony)
log(m->user,"MBOX login: %s Password: %s",m->name,m->line);
else
log(m->user,"MBOX login: %s",m->name);
if(m->privs & EXCLUDED_CMD)
return -1;
#ifdef AX25
/*try to set the name as the user-call.
*this is a very crude test! Be careful...
*Login must have at leat 1 digit (0-9) in it,
*and it must be possible to convert it to a call.
*if this doesn't work, disallow the gateway command,
*no matter if this was allowed by priviledges or not.
*Be careful, some one with login name '4us' and
*permission set to allow gateway/netrom, will
*go out as '4us-15' or '4us-0' !!!!!
*11/15/91 WG7J/PA3DIS
*/
for(cp=m->name;*cp != '\0';cp++)
if(isdigit((int)*cp))
break;
if(*cp != '\0')
founddigit = 1;
if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
m->privs &= ~AX25_CMD;
m->privs &= ~NETROM_CMD;
}
#else
m->privs &= ~AX25_CMD;
m->privs &= ~NETROM_CMD;
#endif /* AX25 */
/* Set the morerows to MAXLIN for telnet logins - WG7J */
m->morerows = MAXLIN - 1;
return 0;
}
tputs("Login incorrect\n");
log(m->user,"MBOX Login failed: %s, pw %s",m->name,m->line);
mail_error("MBOX Login failed: %s, pw %s",m->name,m->line);
*m->name = '\0'; /* wipe any garbage */
}
}
return 0;
}
/* put up the prompt */
void
putprompt(m)
struct mbx *m;
{
char area[64];
char *cp1,*cp2;
#ifdef MAILCMDS
if(m->sid & MBX_SID)
tputs(">\n");
else {
#endif
if(m->sid & MBX_NRID)
tputs(Mbnrid);
#ifdef MAILCMDS
if(m->sid & MBX_AREA) {
cp1 = m->area;
cp2 = area;
/* Convert / and \ into . */
while(*cp1 != '\0') {
if(*cp1=='/')
*cp2 = '.';
else
*cp2 = *cp1;
cp1++;
cp2++;
}
*cp2 = '\0';
tprintf("Area: %s ",area);
}
#endif
tprintf((m->sid & MBX_EXPERT) ? ">\n" : Mbmenu, m->current);
#ifdef MAILCMDS
}
#endif
}
#ifdef MBXTDISC
/* Mailbox user has been idle for too long,
* disconnect the socket - WG7J
*/
void
#ifdef PROTOTYPES
mboxredundant(struct mbx *m)
#else
mboxredundant(m)
struct mbx *m;
#endif
{
struct usock *up;
/* nasty hack! we may have screwed up reference count */
/* by invoking newproc("smtp_send",....); Fudge it! */
if((up = itop(m->user)) != NULLUSOCK)
up->refcnt = 1;
/* Close the socket*/
close_s(m->user);
return; /* Keep lint happy */
}
#endif
/* Incoming mailbox session */
void
mbx_incom(s,t,p)
int s;
void *t;
void *p;
{
#ifdef TIPMAIL
#ifdef XMODEM
struct tipcb *tip;
#endif
#endif
struct mbx *m,*mp,*pp;
struct usock *up;
char *buf[3];
char tmp[AXBUF];
int rval;
FILE *fp;
/*
if((up = itop(s)) != NULLUSOCK)
if(up->iface->flags & NO_AX25)
*/
sockmode(s,SOCK_ASCII);
sockowner(s,Curproc); /* We own it now */
/* Secede from the parent's sockets, and use the network socket that
* was passed to us for both input and output. The reference
* count on this socket will still be 1; this allows the domboxbye()
* command to work by closing that socket with a single call.
* If we return, the socket will be closed automatically.
*/
close_s(Curproc->output);
close_s(Curproc->input);
Curproc->output = Curproc->input = s;
/* We'll do our own flushing right before we read input */
setflush(s,-1);
if((m = newmbx()) == NULLMBX){
tputs("Too many mailbox sessions\n");
return;
}
m->user = s;
m->escape = 20; /* default escape character is Ctrl-T */
m->linemode = 0;
m->type = (int) t;
#ifdef TIPMAIL
#ifdef XMODEM
if(m->type == TIP_LINK) {
tip = (struct tipcb *) p;
tip->raw=0;
m->tip=tip;
}
#endif
#endif
/* discard any remaining input */
/*
while(socklen(s,0))
recv_mbuf(s,NULL,0,NULLCHAR,0);
*/
/* get the name of the remote station */
if(mbx_getname(m) == -1) {
exitbbs(m);
return;
}
Totallogins++;
#ifdef CONVERS
if((int)t & CONF_LINK) {
if(m->privs & NO_CONVERS) {
tputs(Noperm);
mail_error("%s: conv-call access denied\n",m->name);
} else {
m->state = MBX_CONVERS;
chname(Curproc,"conference");
log(s,"open CONF");
mbox_converse(m);
}
/* now free it from list */
for(mp=Mbox,pp=NULLMBX;mp!=m;pp=mp,mp=mp->next);
if(pp==NULLMBX) /* first one on list */
Mbox = m->next;
else
pp->next = m->next;
free((char *)m);
BbsUsers--;
close_s(Curproc->output);
return;
}
#endif
#ifdef TTYCALL
if((int)t & TTY_LINK) {
int ostate = m->state;
m->state = MBX_CHAT;
chname(Curproc,"ttylink");
log(s,"open TTYLINK");
if (dochat(0, 0, m) == 2)
{
/* now free it from list */
for(mp=Mbox,pp=NULLMBX;mp!=m;pp=mp,mp=mp->next);
if(pp==NULLMBX) /* first one on list */
Mbox = m->next;
else
pp->next = m->next;
free((char *)m);
BbsUsers--;
close_s(Curproc->output);
return;
}
tputs("Chaining to BBS...\n");
m->state = ostate;
}
#endif
log(s,"open MBOX");
#ifdef MBXTDISC
/*Start inactivity timer - WG7J */
set_timer(&m->tdisc,Mbtdiscinit * 1000L);
m->tdisc.func = (void(*)__FARGS((void*)))mboxredundant;
m->tdisc.arg = m;
start_timer(&m->tdisc);
#endif
if(m->privs & IS_BBS)
m->sid = MBX_SID; /*force bbs status*/
else
if(m->privs & IS_EXPERT)
m->sid |= MBX_EXPERT;
loguser(m);
m->state = MBX_CMD; /* start in command state */
#ifdef MAILCMDS
tputs(MboxId);
#endif
/* Say 'hello' only if user is not a bbs - WG7J */
#ifdef MAILCMDS
if(!(m->sid & MBX_SID)) {
#endif
tprintf(Mbwelcome,m->name);
#ifdef AX25
if(m->family == AF_INET)
#endif
tprintf(Mbbanner,Hostname,Version);
#ifdef AX25
else
tprintf(Mbbanner,pax25(tmp,Mycall),Version);
#endif
/* How many users are there currently ? */
tprintf(CurUsers,BbsUsers);
#ifdef MAILCMDS
/* Do we accept third party mail ? */
if(!ThirdParty)
tputs(Mbwarning);
#endif
tputc('\n');
/* Is there a message of the day ? */
if((fp = fopen(Motdfile,READ_TEXT)) != NULLFILE) {
sendfile(fp,m->user,ASCII_TYPE,0);
fclose(fp);
}
#ifdef MAILCMDS
#ifdef USERLOG
/* Tell about new arrived mail in message areas - WG7J */
if(Mbnewmail)
listnewmail(m);
#endif
#endif
/* make sure user gets it */
/* usflush(m->user); done in mbxrecvline() */
#ifdef MAILCMDS
/* Enable our local message area,
* only if we're not a bbs - WG7J
*/
buf[1] = m->name;
doarea(2,buf,m);
}
#endif
/* Send prompt */
putprompt(m);
while(mbxrecvline(m) != -1){
if((rval = mbx_parse(m)) == -2)
break;
if(rval == 1)
tputs("Bad syntax.\n");
#ifdef notdef
tprintf("last = %ld, new last = %ld\n",m->lastread,m->newlastread);
#endif
#ifdef MAILCMDS
/* Only tell about new mail when in our own area - WG7J */
if(!(m->sid & MBX_SID) && !strcmp(m->name,m->area) &&
(isnewprivmail(m) > 0L) )
tputs("You have new mail. Please Kill when read!\n");
/* Do not check mailfile if we're bbs, saves a tmpfile- WG7J*/
if(!(m->sid & MBX_SID))
scanmail(m);
#endif
putprompt(m);
m->state = MBX_CMD;
}
exitbbs(m);
/* by invoking newproc("smtp_send",....); Fudge it! */
if((up = itop(Curproc->output)) != NULLUSOCK)
up->refcnt = 1;
close_s(Curproc->output);
}
void
exitbbs(m)
struct mbx *m;
{
struct mbx *mp,*pp;
#ifdef MBXTDISC
stop_timer(&m->tdisc);
#endif
closenotes(m);
free(m->to);
free(m->tofrom);
free(m->origto);
free(m->origbbs);
free(m->subject);
free(m->date);
free(m->tomsgid);
free(m->path);
/* Close the tempfiles if they are not nullpointers - WG7J */
if(m->tfile != (FILE *) 0)
fclose(m->tfile);
if(m->tfp != (FILE *) 0)
fclose(m->tfp);
if(m->stdinbuf != NULLCHAR)
free(m->stdinbuf);
if(m->stdoutbuf != NULLCHAR)
free(m->stdoutbuf);
free((char *)m->mbox);
/* now free it from list */
for(mp=Mbox,pp=NULLMBX;mp && mp!=m;pp=mp,mp=mp->next);
if(!mp)
/* what happened ??? */
return;
if(pp==NULLMBX) /* first one on list */
Mbox = Mbox->next;
else
pp->next = m->next;
free((char *)m);
BbsUsers--;
}
/**********************************************************************/
extern int dombconnect __ARGS((int argc,char *argv[],void *p));
#ifdef CALLBOOK
static int dombcall __ARGS((int argc,char *argv[],void *p));
#endif
extern int dodownload __ARGS((int argc,char *argv[],void *p));
extern int dombupload __ARGS((int argc,char *argv[],void *p));
extern int dowhat __ARGS((int argc,char *argv[],void *p));
extern int dozap __ARGS((int argc,char *argv[],void *p));
static int dosend __ARGS((int argc,char *argv[],void *p));
extern int dosid __ARGS((int argc,char *argv[],void *p));
extern int dosysop __ARGS((int argc,char *argv[],void *p));
extern int dostars __ARGS((int argc,char *argv[],void *p));
static int dombhelp __ARGS((int argc,char *argv[],void *p));
static int dombiproute __ARGS((int argc,char *argv[],void *p));
extern int dombtelnet __ARGS((int argc,char *argv[],void *p));
extern int dombfinger __ARGS((int argc,char *argv[],void *p));
static int dombexpert __ARGS((int argc,char *argv[],void *p));
static int dombjheard __ARGS((int argc,char *argv[],void *p));
int dombmovemail __ARGS((int argc,char *argv[],void *p));
void gw_alarm __ARGS((void *p));
void gw_input __ARGS((int s,void *notused,void *p));
void gw_superv __ARGS((int null,void *proc,void *p));
extern int mbx_to __ARGS((int argc,char *argv[],void *p));
extern int mbx_data __ARGS((struct mbx *m,struct list *cclist,char *extra));
int msgidcheck __ARGS((char *string));
extern int thirdparty __ARGS((struct mbx *m));
#ifdef NETROM
extern int dombnrnodes __ARGS((int argc,char *argv[],void *p));
extern int donrneighbour __ARGS((int argc,char *argv[],void *p));
#endif
static struct cmds DFAR Mbcmds[] = {
"", doreadnext, 0, 0, NULLCHAR,
"?", dombhelp, 0, 0, NULLCHAR,
#ifdef MAILCMDS
"area", doarea, 0, 0, NULLCHAR,
#endif
"bye", domboxbye, 0, 0, NULLCHAR,
"connect", dombconnect,0, 0, NULLCHAR,
#ifdef CALLBOOK
"call", dombcall, 0, 0, NULLCHAR,
#endif
#ifdef XMODEM
"download", dodownload, 0, 2, "D[U|X] <filename>",
#else
"download", dodownload, 0, 2, "D[U] <filename>",
#endif
"escape", dombescape, 0, 0, NULLCHAR,
"finger", dombfinger, 0, 0, NULLCHAR,
"help", dombhelp, 0, 0, NULLCHAR,
"info", dombhelp, 0, 0, NULLCHAR,
"iheard", doipheard,0, 0, NULLCHAR,
"iproute", dombiproute,0, 0, NULLCHAR,
#ifdef AX25
"jheard", dombjheard, 0, 0, NULLCHAR,
#endif
#ifdef MAILCMDS
"kill", dodelmsg, 0, 0, NULLCHAR,
"list", dolistnotes,0, 0, NULLCHAR,
#endif
"mboxusers",dombusers, 0, 0, NULLCHAR,
#ifdef NETROM
"nodes", dombnrnodes,0, 0, NULLCHAR,
"nroutes", donrneighbour, 0, 0, NULLCHAR,
#endif
"operator", dochat, 0, 0, NULLCHAR,
"ports", dombports, 0, 0, NULLCHAR,
#ifdef CALLCLI
"query", dombcallbook, 0, 2, "Q callsign\nMultiple callsigns allowed per line",
#endif
#ifdef MAILCMDS
"read", doreadmsg, 0, 0, NULLCHAR,
"send", dosend, 0, 0, NULLCHAR,
#endif
"telnet", dombtelnet, 0, 2, "T hostname",
#ifdef XMODEM
"upload", dombupload, 0, 2, "U[X] <filename>",
#else
"upload", dombupload, 0, 2, NULLCHAR,
#endif
#ifdef MAILCMDS
"verbose", doreadmsg, 0, 0, NULLCHAR,
#endif
"what", dowhat, 0, 0, NULLCHAR,
"xpert", dombexpert, 0, 0, NULLCHAR,
"zap", dozap, 0, 2, "Z filename",
#ifdef MAILCMDS
"[", dosid, 0, 0, NULLCHAR,
#ifdef AX25
#ifdef MBFWD
"f>", dorevfwd, 0, 0, NULLCHAR,
#endif
#endif
#endif
"@", dosysop, 0, 0, NULLCHAR,
"***", dostars, 0, 0, NULLCHAR,
NULLCHAR, NULLFP((int,char**,void*)), 0, 0, "Huh?",
};
/* "twocmds" defines the MBL/RLI two-letter commands, eg. "SB", "SP" and so on.
* They have to be treated specially since cmdparse() wants a space between
* the actual command and its arguments.
* "SP FOO" is converted to "s foo" and the second command letter is saved
* in m->stype. Longer commands like "SEND" are unaffected, except for
* commands starting with "[", i.e. the SID, since we don't know what it will
* look like.
*/
static char twocmds[] = "aslrd[muvkx"; /* S,L,R,D,M,U,V,K,X are two-letter commands */
int
mbx_parse(m)
struct mbx *m;
{
char *cp;
int i;
char *newargv[2];
/* Translate entire buffer to lower case */
for (cp = m->line; *cp != '\0'; ++cp)
if(isupper(*cp))
*cp = tolower(*cp);
/* Skip any spaces at the begining */
for(cp = m->line;isspace(*cp);++cp)
;
m->stype = ' ';
if(*cp != '\0' && *(cp+1) != '\0')
for(i=0; i<strlen(twocmds); ++i){
if(*cp == twocmds[i] && (isspace(*(cp+2)) || *(cp+2) == '\0'
|| *cp == '[')){
if(islower(*(++cp)))
m->stype = toupper(*cp); /* Save the second character */
else
m->stype = *cp;
*cp = ' ';
break;
}
}
#ifdef MAILCMDS
/* See if the input line consists solely of digits */
cp = m->line;
for(cp = m->line;isspace(*cp);++cp)
;
newargv[1] = cp;
for(;*cp != '\0' && isdigit(*cp);++cp)
;
if(*cp == '\0' && strlen(newargv[1]) > 0) {
newargv[0] = "r";
return doreadmsg(2,newargv,(void *)m);
}
else
#endif
return cmdparse(Mbcmds,m->line,(void *)m);
}
/* This works like recvline(), but telnet options are answered and the
* terminating newline character is not put into the buffer. If the
* incoming character equals the value of escape, any queued input is
* flushed and -2 returned.
*/
int
mbxrecvline(m)
struct mbx *m;
{
int s = m->user;
int escape = m->escape;
char *buf = m->line;
int c, cnt = 0, opt, cl;
if(buf == NULLCHAR)
return 0;
usflush(Curproc->output);
#ifdef MBXTDISC
start_timer(&m->tdisc);
#endif
while((c = recvchar(s)) != EOF){
if(c == IAC){ /* Telnet command escape */
if((c = recvchar(s)) == EOF)
break;
if(c >= 250 && c < 255 && (opt = recvchar(s)) != EOF){
switch(c){
case SB:
opt=recvchar(s); /* Get the real option */
if(opt==EOF) break;
cl=opt;
c=recvchar(s);
/* Gobble up until we see IAC SE */
while((c!=EOF) && !(cl==IAC && c==SE)){
/* maybe check for timeout here, in case someone
happened to send a binary file with the IAC SB
sequence in it. */
cl=c; /* keep track of second last char read */
c=recvchar(s);
}
/* and tell the client where to go... */
/* tprintf("%c%c%c",IAC,WONT,opt); */
break;
case WILL:
if(opt==TN_LINEMODE){
m->linemode = 1;
/* we WANT linemode */
tprintf("%c%c%c",IAC,DO,opt);
/* Tell client to do editing */
tprintf("%c%c%c%c%c%c%c",IAC,SB,TN_LINEMODE,1,1,IAC,SE);
}
else{
tprintf("%c%c%c",IAC,DONT,opt);
}
break;
case WONT:
tprintf("%c%c%c",IAC,DONT,opt);
break;
case DO:
tprintf("%c%c%c",IAC,WONT,opt);
break;
case DONT:
tprintf("%c%c%c",IAC,WONT,opt);
}
/* to be fixed usflush(Curproc->output);*/
continue;
}
if(c != IAC && (c = recvchar(s)) == EOF)
break;
}
/* ordinary character */
if(c == '\r' || c == '\n')
break;
if(uchar(c) == escape){
if(socklen(s,0)) /* discard any remaining input */
recv_mbuf(s,NULL,0,NULLCHAR,0);
cnt = -2;
break;
}
/* Handle <del> chars - from wa7tas */
if(c == 8) {
if(cnt > 0) {
*--buf = 0;
cnt--;
}
} else {
*buf++ = c;
++cnt;
}
if(cnt == MBXLINE - 1)
break;
}
if(c == EOF && cnt == 0)
return -1;
*buf = '\0';
#ifdef MBXTDISC
/* Restart the timeout-timer - WG7J*/
start_timer(&m->tdisc);
#endif
return cnt;
}
extern void updatedefaults(struct mbx *);
int
domboxbye(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
m = (struct mbx *)p;
/* for bbs's, just disconnect */
if(m->sid & MBX_SID)
return -2;
#ifdef USERLOG
setlastread(m);
updatedefaults(m);
#endif
/* Now say goodbye */
tprintf("\nThank you %s,\nfor calling the %s NOS Tcp/Ip Mailbox.\n\n",m->name,
Hostname);
#ifdef ALLSERV
if(m->type == TIP_LINK)
tputs("Please hang up now.\n");
#endif
usflush(m->user);
return -2; /* signal that exitbbs() should be called */
}
static int
dombhelp(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char buf[255];
int i;
FILE *fp;
if(*argv[0] == '?') {
tputs(Longmenu);
return 0;
}
buf[0] = '\0';
if(argc > 1)
for(i=0; Mbcmds[i].name != NULLCHAR; ++i)
if(!strncmp(Mbcmds[i].name,argv[1],strlen(argv[1]))) {
sprintf(buf,"%s/%s.hlp",Helpdir,Mbcmds[i].name);
break;
}
if(buf[0] == '\0')
if(*argv[0] == 'i') {
/* INFO command */
tprintf(Nosversion,Version);
sprintf(buf,"%s/info.hlp",Helpdir);
} else
sprintf(buf,"%s/help.hlp",Helpdir);
if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
sendfile(fp,Curproc->output,ASCII_TYPE,0);
fclose(fp);
} else {
if(*argv[0]!='i')
tputs("No help available.\n");
}
return 0;
}
extern void dumproute __ARGS((struct route *rp,char *p));
extern char RouteHeader[];
/* Show non-private routes only */
int
dombiproute(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register int i,bits;
register struct route *rp;
char buf[85];
tputs(RouteHeader);
for(bits=31;bits>=0;bits--){
for(i=0;i<HASHMOD;i++){
for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
if(!(rp->flags & RTPRIVATE)) {
dumproute(rp,buf);
if(tprintf("%s\n",&buf[4]) == EOF)
return 0;
}
}
}
}
if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)) {
dumproute(&R_default,buf);
if(tprintf("%s\n",&buf[4]) == EOF)
return 0;
}
return 0;
}
#ifdef MAILCMDS
extern char Badmsg[];
extern char Nomail[];
/* Move messages from current area to another */
int
dombmovemail(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int num,i;
int move[NARG];
char *to;
struct mbx *m;
char buf[MBXLINE];
#ifdef notdef
char *cp;
#endif
FILE * Mfile; /* file to move to */
struct let *cmsg;
long size;
int thisone;
m = (struct mbx *)p;
if(argc == 1) {
tputs("Syntax: MM area - moves current message\n"
" MM n1 [n2...] area - move message n1 (n2...)\n");
return 0;
}
if(m->mfile == NULLFILE) {
tputs(Nomail);
return 0;
}
if(argc == 2) {
/* NO message #, use current message */
num = 1;
to = argv[1];
move[0] = m->current;
} else {
/* Scan all message # to move */
num=0;
for(i=1;i<argc-1;i++) {
if( (move[num]=atoi(argv[i])) != 0 ) {
if(move[num] <= m->nmsgs)
num++;
} else
tprintf(Badmsg,argv[i]);
}
to = argv[argc-1];
}
#ifdef notdef
/* translate '.' and '\\' to '/' */
for(cp=to;*cp!='\0';cp++)
if((*cp == '.') || (*cp == '\\'))
*cp = '/';
#endif
/* Now try to lock the destination file */
if(mlock(Mailspool,to) == -1) {
tprintf("Can't lock '%s', please try later\n",to);
return 0;
}
/* open the destination file for appending */
sprintf(buf,"%s/%s.txt",Mailspool,to);
if((Mfile=fopen(buf,"a")) == NULLFILE) {
tprintf("Can't open '%s'\n",buf);
rmlock(Mailspool,to);
return 0;
}
/* Okay, let's do the work */
for(i=0;i<num;i++) {
thisone = move[i];
cmsg = &m->mbox[thisone];
/* find start of this message */
fseek(m->mfile,cmsg->start,0);
size = cmsg->size;
/* now read this message */
while(size > 0 && fgets(buf,MBXLINE,m->mfile)!= NULLCHAR) {
fputs(buf,Mfile);
size -= strlen(buf);
}
/* delete this message */
cmsg->status |= BM_DELETE;
m->change = 1;
tprintf("Message %d moved...\n",thisone);
}
fclose(Mfile);
rmlock(Mailspool,to);
return 0;
}
#endif
static int
dombexpert(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
m = (struct mbx *)p;
switch(m->stype) {
case 'M':
if(argc == 1)
tprintf("-more- after %d lines\n",m->morerows);
else {
m->morerows = atoi(argv[1]);
}
break;
case 'A':
m->sid ^= MBX_AREA;
break;
case 'N':
m->sid ^= MBX_NRID;
break;
default:
m->sid ^= MBX_EXPERT;
break;
}
return 0;
}
extern char SysopBusy[];
static int
dochat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char buf[8], *newargv[3];
struct mbx *m;
m = (struct mbx *)p;
if(MAttended){
m->state = MBX_CHAT;
newargv[0] = "C";
newargv[1] = Hostname;
sprintf(buf,"%d",IPPORT_TTYLINK);
newargv[2] = buf;
return dombtelnet(3,newargv,p);
}
else {
tputs(SysopBusy);
}
/* It returns only after a disconnect or refusal */
return 0;
}
#ifdef AX25
static int
dombjheard(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
struct mbx *m = (struct mbx *)p;
if(argc > 1){
if( ((ifp = if_lookup(argv[1])) == NULLIF) || (ifp->type != CL_AX25) ||
((ifp->flags & HIDE_PORT) && !(m->privs & MBX_SYSOP)) ) {
tprintf(Badinterface,argv[1]);
return 0;
}
axheard(ifp);
return 0;
}
for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
if((ifp->flags & LOG_AXHEARD) && ( !(ifp->flags & HIDE_PORT) || m->privs&MBX_SYSOP) )
if(axheard(ifp) == EOF)
break;
}
return 0;
}
#endif
#ifdef CALLBOOK
extern char *InetCallserver;
extern char *InetCallserverport;
/*This is a simple way of estiblishing a connection
*to a callbook-server via tcp - WG7J
*/
static int
dombcall(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char *newargv[3];
if(InetCallserver!=NULLCHAR){
newargv[0] = "C";
newargv[1] = InetCallserver;
newargv[2] = InetCallserverport;
return dombtelnet(3,newargv,p);
}
else {
tputs("Internet callserver not configured\n");
}
/* It returns only after a disconnect or refusal */
return 0;
}
#endif /*CALLBOOK*/
#ifdef CALLCLI
static int
dombcallbook(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
char buf[8], *newargv[3];
extern char *Callserver;
int req, ret = 0;
m = (struct mbx *) p;
/* tprintf("Looking up - %s - in the callbook at %s\n",argv[1],Callserver);*/
sprintf(buf,"%d",IPPORT_CALLDB);
newargv[0] = "C";
newargv[1] = Callserver;
newargv[2] = buf;
for (req = 1; req < argc; req++) {
if (argv[req] == NULLCHAR) return ret;
m->startmsg = mallocw(80); /* is freed each time by gw_connect() */
sprintf(m->startmsg,"%s\n", argv[req]);
log(m->user, "%s checking callbook: %s",m->name,argv[req]);
tprintf("Looking for \" %s \" in the callbook at %s\n",argv[req],Callserver);
ret = dombtelnet(3,newargv,p);
}
return ret; /* It looks like all possible returns are zero anyway! */
}
#endif
#ifdef MAILCMDS
extern int Mbloophold;
/*Some additional security - WG7J
*NO_3PARTY = disallow all 3rd party mail
*NO_SENDCMD = only allow mail to sysop
*/
extern int NoBid;
static int
dosend(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int cccnt = 0, fail = 0;
char *host, *cp, fullfrom[MBXLINE], sigwork[LINELEN], *rhdr = NULLCHAR;
struct list *ap, *cclist = NULLLIST;
struct mbx *m;
FILE *fp;
#ifdef notdef
time_t now;
#endif
int done = 0;
char *cp2;
int c;
#ifdef RLINE
struct tm t;
#define ODLEN 16
#define OBLEN 32
char tmpline[MBXLINE];
char fwdbbs[NUMFWDBBS][FWDBBSLEN+1];
int myfwds = 0;
int i;
int zulu;
int check_r = 0;
int found_r = 0;
char origdate[ODLEN];
char origbbs[OBLEN];
int loops = 0;
char Me[15];
origdate[0] = '\0';
origbbs[0] = '\0';
#endif
m = (struct mbx *)p;
if((m->stype != 'R' || (m->sid & MBX_SID)) && mbx_to(argc,argv,m)
== -1){
tputs((m->sid & MBX_SID) ? "NO - syntax error\n" : \
"S command syntax error - format is:\n" \
"S[C|F] name [@ host] [< from_addr] [$bulletin_id]\n" \
"SR [number]\n");
mail_error("%s: MBOX S syntax error - %s\n",m->name,m->line);
return 0;
}
/*Check for send permission */
if(m->privs & NO_SENDCMD) { /*is this to 'SYSOP' or 'sysop' ?*/
if(stricmp(m->to,"sysop")) {
tputs((m->sid & MBX_SID) ? "NO - permission denied\n" : \
"Sorry, only mail to 'sysop' allowed!\n");
mail_error("%s: no mail permission - %s\n",m->name,m->to);
return 0;
}
}
/* Check for a BID on bulletins from other bbs's - WG7J */
if((m->sid & MBX_SID) && !NoBid &&
(m->stype == 'B') && (m->tomsgid == NULLCHAR)) {
tputs("NO - No BID!\n");
log(m->user,"%s: SB without BID - %s",m->name,m->to);
mail_error("%s: SB without BID - %s",m->name,m->to);
return 0;
}
if(m->stype != 'R' && msgidcheck(m->tomsgid)) {
if(m->sid & MBX_SID)
tputs("NO - ");
tprintf("Already have %s\n",m->tomsgid);
return 0;
}
if(m->stype == 'R' && !(m->sid & MBX_SID) &&
mbx_reply(argc,argv,m,&cclist,&rhdr) == -1)
return 0;
if((cp = rewrite_address(m->to)) != NULLCHAR)
if(strcmp(m->to,cp) != 0){
m->origto = m->to;
m->to = cp;
}
else
free(cp);
/* refuse any mail that gets rewritten into 'refuse' - WG7J */
if(!strcmp(m->to,"refuse")) {
tputs((m->sid & MBX_SID) ? "NO - refused\n" : \
"Bad user or hostname, please mail 'sysop' for help\n");
return 0;
}
if( (!ThirdParty && !(m->privs & SYSOP_CMD)) || (m->privs & NO_3PARTY) )
if(thirdparty(m) == 0){
tputs(Mbwarning);
mail_error("%s: 3rd party mail refused - %s\n",m->name,m->to);
return 0;
}
/* Send the new 'To:' line to sysops only - WG7J */
if((m->privs&SYSOP_CMD) && (m->origto != NULLCHAR || m->stype == 'R') \
&& !(m->sid & MBX_SID))
tprintf("To: %s\n", m->to);
if(validate_address(m->to) == 0){
tputs((m->sid & MBX_SID) ? "NO - bad address\n" : \
"Bad user or hostname, please mail 'sysop' for help\n");
free(rhdr);
del_list(cclist);
/* We don't free any more buffers here. They are freed upon
* the next call to mbx_to() or to domboxbye()
*/
return 0;
}
/* Display the Cc: line (during SR command) */
for(ap = cclist; ap != NULLLIST; ap = ap->next) {
if(cccnt == 0){
tprintf("%s",Hdrs[CC]);
cccnt = 4;
}
else {
tputs(", ");
cccnt += 2;
}
if(cccnt + strlen(ap->val) > 80 - 3) {
tputs("\n ");
cccnt = 4;
}
tputs(ap->val);
cccnt += strlen(ap->val);
}
if(cccnt)
tputc('\n');
/* If the the command was 'SC' then read the Cc: list now - WG7J */
if((m->stype == 'C') && !(m->sid & MBX_SID)) {
m->stype = 'P'; /* make everything private */
tputs(CcLine);
if(mbxrecvline(m) != -1) {
if(strlen(m->line)) {
if(*m->line == 0x01) { /* CTRL-A, abort */
free(rhdr);
del_list(cclist);
tputs(MsgAborted);
return 0;
}
cp = m->line;
/* get all the Cc addresses, separated by comma's */
while((cp2=strchr(cp,',')) != NULLCHAR) {
*cp2 = '\0';
/*get rid of leading spaces or tabs*/
while(*cp == ' ' || *cp == '\t')
cp++;
if(strlen(cp))
addlist(&cclist,cp,0);
cp = cp2 + 1;
}
/* Do the last or only one */
/* get rid of leading spaces or tabs*/
while(*cp == ' ' || *cp == '\t')
cp++;
if(strlen(cp))
addlist(&cclist,cp,0);
}
} else {
free(rhdr);
del_list(cclist);
return 0;
}
}
/* Now check to make sure we can create the needed tempfiles - WG7J */
if((m->tfile = tmpfile()) == NULLFILE) {
free(rhdr);
del_list(cclist);
/*
tputs((m->sid & MBX_SID) ? "NO - no temp file\n" : \
"Can't create temp file for mail\n");
return 0;
*/
/* instead of saying NO and have the other bbs think we already
* have the message, disconnect !
*/
if(m->sid & MBX_SID)
return -2;
/* tell regualr users about it */
tputs("Can't create temp file for mail\n");
return 0;
}
#ifdef RLINE
/* Only accept R: lines from bbs's */
if((m->sid & MBX_SID)&&(Rdate || Rreturn || Rfwdcheck || Mbloophold)){
/* Going to interpret R:headers,
* we need another tempfile !
*/
if((m->tfp = tmpfile()) == NULLFILE) {
free(rhdr);
del_list(cclist);
/*
tputs("NO - no temp file\n");
return 0;
*/
/* disconnect to avoid the other bbs to think that we already have
* the message !
*/
return -2;
}
/* Now we got enough :-) */
check_r = 1;
Checklock++;
/* Set the call, used in loop detect code - WG7J */
if(Mbloophold) {
pax25(Me,Mycall);
if((cp = strchr(Me,'-')) != NULLCHAR)
*cp = '\0'; /* remove SSID */
}
}
#endif
m->state = MBX_SUBJ;
if(m->stype != 'R' || (m->sid & MBX_SID)) {
/* This might bollix incoming forwarding, we'll see: suggested by
N6NKO in mail that \n after Subject: become a space. Brandon */
tputs((m->sid & MBX_SID) ? "OK\n" : "Subject: ");
if(mbxrecvline(m) == -1) {
#ifdef RLINE
if(check_r) {
MYFCLOSE(m->tfp);
Checklock--;
}
#endif
return 0;
}
}
else /* Replying to a message */
tprintf("Subject: %s\n",m->line);
m->subject = strdup(m->line);
#ifdef RLINE
if(!check_r) {
#endif
mbx_data(m,cclist,rhdr);
/*Finish smtp headers*/
fprintf(m->tfile,"\n");
#ifdef RLINE
}
#endif
free(rhdr);
m->state = MBX_DATA;
if(!(m->sid & MBX_SID) && m->stype != 'F')
tprintf("Enter message. %s",Howtoend);
if(m->stype != 'F' || (m->sid & MBX_SID) != 0) {
while(mbxrecvline(m) != -1){
if(m->line[0] == 0x01){ /* CTRL-A */
MYFCLOSE(m->tfile);
#ifdef RLINE
if(check_r)
MYFCLOSE(m->tfp);
#endif
tputs(MsgAborted);
del_list(cclist);
return 0;
}
if(m->line[0] != CTLZ && stricmp(m->line, "/ex")) {
#ifdef RLINE
if(check_r) {
/* Check for R: lines to start with */
if(!strncmp(m->line,"R:",2)) { /*found one*/
found_r = 1;
/*Write this line to the second tempfile
*for later rewriting to the real one
*/
fprintf(m->tfp,"%s\n",m->line);
/* Find the '@[:]CALL.STATE.COUNTRY'or
* or the '?[:]CALL.STATE.COUNTRY' string
* The : is optional.
*/
if( ((cp=strchr(m->line,'@')) != NULLCHAR) ||
((cp=strchr(m->line,'?')) != NULLCHAR) ) {
if((cp2=strchr(cp,' ')) != NULLCHAR)
*cp2 = '\0';
if((cp2=strchr(cp,'\n')) != NULLCHAR)
*cp2 = '\0';
if((cp2=strchr(cp,'\t')) != NULLCHAR)
*cp2 = '\0';
/* Some bbs's send @bbs instead of @:bbs*/
if (*++cp == ':')
cp++;
/* if we use 'return addres'
* copy whole 'domain' name
*/
if(Rreturn)
if(strlen(cp) <= OBLEN)
strcpy(origbbs,cp);
/* Optimize forwarding ? */
if(Rfwdcheck || Mbloophold) {
/*if there is a HADDRESS, cut off after '.'*/
if((cp2=strchr(cp,'.')) != NULLCHAR)
*cp2 = '\0';
if(Mbloophold)
/* check to see if this is my call ! */
if(!stricmp(Me,cp))
loops++;
/*cross-check with MyFwds list*/
if(Rfwdcheck) {
for(i=0;i<Numfwds;i++) {
if(!strcmp(MyFwds[i],cp)) {
/*Found one !*/
strcpy(fwdbbs[myfwds++],cp);
break;
}
}
}
}
}
if(Rdate) {
/* Find the 'R:yymmdd/hhmmz' string */
if((cp=strchr(m->line,' ')) != NULLCHAR) {
*cp = '\0';
if(strlen(m->line+2) <= ODLEN)
strcpy(origdate,m->line+2);
}
}
} else {
/* The previous line was last R: line
* so we're done checking
* now write the smtp headers and
* all saved R: lines to the right tempfile
*/
check_r = 0;
Checklock--;
/*Did we actually find one ?*/
if(found_r) {
if(Rreturn)
m->origbbs = strdup(strlwr(origbbs));
if(Rdate) {
if((cp=strchr(origdate,'/')) != NULLCHAR) {
zulu = 0; /* not initialized before! */
if((*(cp+5) == 'z') || (*(cp+5) == 'Z')) {
*(cp+5) = '\0';
zulu = 1;
}
t.tm_min = atoi(cp+3);
*(cp+3) = '\0';
t.tm_hour = atoi(cp+1);
*cp = '\0';
t.tm_mday = atoi(&origdate[4]);
origdate[4] = '\0';
t.tm_mon = (atoi(&origdate[2]) - 1);
origdate[2] = '\0';
t.tm_year = atoi(origdate);
/* Set the date in rfc 822 format */
m->date = mallocw(40);
sprintf(m->date,"%.2d %s %02d %02d:%02d:00 %.3s\n",
t.tm_mday,
Months[t.tm_mon],
t.tm_year,
t.tm_hour,
t.tm_min,
zulu ? "UTC" : "");
}
}
}
/* Now write the headers,
* possibly adding Xforwarded lines for bulletins,
* or anything that has a BID.
* Add the X-Forwarded lines and loop detect
* headers FIRST,
* this speeds up forwarding...
*/
if(Mbloophold && loops >= Mbloophold)
fprintf(m->tfile,"%sLoop\n",Hdrs[XBBSHOLD]);
if(Rfwdcheck && found_r && \
((m->stype == 'B') || (m->tomsgid)) ){
/*write Xforwarded headers*/
for(i=0;i<myfwds;i++) {
fprintf(m->tfile,"%s%s\n",Hdrs[XFORWARD],fwdbbs[i]);
}
}
/*write regular headers*/
mbx_data(m,cclist,rhdr);
/* Finish smtp headers */
fprintf(m->tfile,"\n");
/* Now copy the R: lines back */
if(found_r) {
rewind(m->tfp);
while(fgets(tmpline,sizeof(tmpline),m->tfp)!=NULLCHAR)
fputs(tmpline,m->tfile);
}
MYFCLOSE(m->tfp);
/* And add this first non-R: line */
fprintf(m->tfile,"%s\n",m->line);
}
} else
#endif
fprintf(m->tfile,"%s\n",m->line);
} else {
#ifdef RLINE
if(check_r) {
/* Hmm, this means we never finished the R: headers
* tmp file still open !
*/
MYFCLOSE(m->tfp);
}
#endif
done = 1; /* To indicate the difference between
* mbxrecvline() returning -1 and /ex ! - WG7J
* Now also used to indicate if the message should
* be sent or not !
*/
/* Now ask users if they want to send this ! - WG7J */
if( Mbsendquery && !(m->sid & MBX_SID)) {
if(m->type == TELNET_LINK || m->type == TIP_LINK)
c = tkeywait("Send(N=no)?",0,m->linemode);
else /* For AX.25 and NET/ROM connects */
c = mykeywait("Send(N=no)?",m);
if(c == -1 || c == 'n' || c == 'N') {
done = 0; /* signal delete of message */
tputs(MsgAborted);
}
}
break; /* all done */
}
}
if(!done) {
/* We did NOT get ^Z or /EX, but mbxrecvline returned -1 !!!
* This means the connection is gone ! - WG7J
* Now can also mean that the user doesn't want to send msg !
*/
MYFCLOSE(m->tfile);
#ifdef RLINE
if(check_r)
MYFCLOSE(m->tfp);
#endif
del_list(cclist);
free(rhdr); /*Just in case*/
return 0;
}
} else {
fprintf(m->tfile,"----- Forwarded message -----\n\n");
msgtofile(m,m->current,m->tfile,0);
fprintf(m->tfile,"----- End of forwarded message -----\n");
}
/* Insert customised signature if one is found */
if(!(m->sid & MBX_SID)) { /* not a forwarding BBS */
sprintf(sigwork,"%s/%s.sig",Signature,
m->tofrom ? m->tofrom : m->name);
if((fp = fopen(sigwork,READ_TEXT)) != NULLFILE){
while(fgets(sigwork,LINELEN,fp) != NULLCHAR)
fputs(sigwork,m->tfile);
fclose(fp);
}
}
if((host = strrchr(m->to,'@')) == NULLCHAR) {
host = Hostname; /* use our hostname */
if(m->origto != NULLCHAR) {
/* rewrite_address() will be called again by our
* SMTP server, so revert to the original address.
*/
free(m->to);
m->to = m->origto;
m->origto = NULLCHAR;
}
}
else
host++; /* use the host part of address */
/* make up full from name for work file */
if(m->tofrom != NULLCHAR)
sprintf(fullfrom,"%s%%%s@%s",m->tofrom, m->name, Hostname);
else
sprintf(fullfrom,"%s@%s",m->name,Hostname);
if(cclist != NULLLIST && stricmp(host,Hostname) != 0) {
fseek(m->tfile,0L,0); /* reset to beginning */
fail = queuejob(m->tfile,Hostname,cclist,fullfrom);
del_list(cclist);
cclist = NULLLIST;
}
addlist(&cclist,m->to,0);
fseek(m->tfile,0L,0);
fail += queuejob(m->tfile,host,cclist,fullfrom);
del_list(cclist);
MYFCLOSE(m->tfile);
if(fail){
if(!(m->sid & MBX_SID)) /* only when we're not a bbs */
tputs("Couldn't queue msg!\n");
} else {
if(m->sid & MBX_SID)
MbRecvd++;
else {
tputs("Msg queued\n");
MbSent++;
}
#ifdef notdef
/* BID is now saved in the smtp server ! - WG7J */
if(m->tomsgid != NULLCHAR && \
(fp = fopen(Historyfile,APPEND_TEXT)) != NULLFILE) {
/* Timestamp added to allow automatic expiry of bid file - WG7J */
time(&now);
fprintf(fp,"%s %ld\n",m->tomsgid,now); /* Save BID */
fclose(fp);
}
#endif
}
smtptick(NULL); /* wake SMTP to send that mail */
return 0;
}
#endif /* MAILCMDS */
#endif /* MAILBOX */